package com.skyun.watchmanager;

import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.Environment;
import android.support.annotation.Nullable;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

import com.google.gson.Gson;
import com.skyun.watchserer.common.models.AppInfo;
import com.skyun.watchserer.common.models.Const;
import com.skyun.watchserer.common.models.DeviceInfo;

import junit.framework.Assert;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import me.skyun.androidarch.base.BaseListFragment;
import me.skyun.androidarch.common.IntentEx;
import me.skyun.androidarch.connect.BluetoothServer;
import me.skyun.androidarch.connect.Connection;
import me.skyun.androidarch.connect.Server;
import me.skyun.androidarch.connect.TcpServer;

/**
 * Created by skyun on 17/8/22.
 */

public class MyWatchFragment extends BaseListFragment {

    private TextView mMyDeviceView;
    private TextView mMyDeviceStatusView;

    private TextView mMyWatchFaceView;

    private BluetoothDevice mMyDevice;
    private Connection mConnection;
    private DeviceInfo mDeviceInfo;
    private AppAdapter mAppAdapter;

    private List<String> mWatchFaceNames;

    private TcpServer mTcpServer;

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mAppAdapter = new AppAdapter(getContext());
        mAppAdapter.addAllIcons(getAppIcons(getContext()));
        setListAdapter(mAppAdapter);
        setHasOptionsMenu(true);
    }

    private void startListenEmulator() {
        if (mConnection != null) {
            mConnection.disconnect();
        }
        if (mTcpServer != null) {
            mTcpServer.stopServer();
        }
        mTcpServer = new TcpServer(5602, mServerCallback, mConnCallback);
        mTcpServer.startListen();
    }

    private void startConnectDevice() {
        if (mConnection != null) {
            mConnection.disconnect();
        }
        BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
        if (!adapter.isEnabled()) {
            adapter.enable();
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        Set<BluetoothDevice> deviceSet = adapter.getBondedDevices();
        Iterator<BluetoothDevice> iter = deviceSet.iterator();
        if (iter.hasNext()) {
            mMyDevice = iter.next();
            new BluetoothServer(Const.BLUETOOTH_NAME, Const.BLUETOOTH_UUID, mServerCallback, mConnCallback).startListen();
        } else {
            Toast.makeText(getContext(), "未发现设备", Toast.LENGTH_SHORT).show();
        }
    }

    @Override
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
        inflater.inflate(R.menu.menu_main,menu);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()){
            case R.id.connect_emulator:
                startListenEmulator();
                return true;
            case R.id.connect_watch:
                startConnectDevice();
                return true;
            default:
                return super.onOptionsItemSelected(item);
        }
    }

    @Override
    public void onListItemClick(ListView l, View v, int position, long id) {
        AppInfo appInfo = (AppInfo) l.getItemAtPosition(position);
        new IntentEx(getContext(), InfoActivity.class)
                .putKeyValueExtras("info", appInfo)
                .startActivity(this);
    }

    private Server.Callback mServerCallback = new Server.DefaultCallback() {
        @Override
        public void onListenStarted() {
            mMyDeviceStatusView.setText("[监听连接中...]");
        }
    };

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        if (mConnection != null) {
            mConnection.disconnect();
        }
    }

    private View inflateHeader() {
        View header = View.inflate(getContext(), R.layout.my_watch_header, null);
        mMyDeviceView = (TextView) header.findViewById(R.id.my_watch_tv_my_device);
        mMyDeviceStatusView = (TextView) header.findViewById(R.id.my_watch_tv_my_device_status);
        mMyWatchFaceView = (TextView) header.findViewById(R.id.my_watch_tv_watch_face);
        header.findViewById(R.id.my_watch_layout_my_device).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (mDeviceInfo == null) {
                    Toast.makeText(v.getContext(), "设备未连接", Toast.LENGTH_SHORT).show();
                    return;
                }
                new IntentEx(getContext(), InfoActivity.class)
                        .putKeyValueExtras("info", mDeviceInfo)
                        .startActivity(MyWatchFragment.this);
            }
        });
//        header.findViewById(R.id.my_watch_tv_connect_emulator).setOnClickListener(new View.OnClickListener() {
//            @Override
//            public void onClick(View v) {
//                startListenEmulator();
//            }
//        });
//        header.findViewById(R.id.my_watch_tv_connect_watch).setOnClickListener(new View.OnClickListener() {
//            @Override
//            public void onClick(View v) {
//                startConnectDevice();
//            }
//        });
        return header;
    }

    private Connection.Callback mConnCallback = new Connection.DefaultCallback() {
        @Override
        public void onStateChanged(Connection connection, Connection.State state) {
            if (state == Connection.State.Connected) {
                mConnection = connection;
                connection.sendMessage("app");
//                connection.sendString("info");
            }
            if (getView() != null) {
                if (state == Connection.State.Connecting) {
                    mMyDeviceStatusView.setText("[连接中]");
                } else if (state == Connection.State.Connected) {
                    mMyDeviceStatusView.setText("[已连接]");
                } else if (state == Connection.State.Disconnected) {
                    mMyDeviceStatusView.setText("[未连接]");
                    mConnection = null;
                }
            }
        }

        @Override
        public void onReceive(Connection connection, String name, Bitmap bitmap) {
            mAppAdapter.addIcon(name, bitmap);
            mAppAdapter.notifyDataSetChanged();
            saveAppIconImage(name, bitmap);
        }

        @Override
        public void onReceiveObject(Connection connection, Object obj) {
            if (obj instanceof DeviceInfo) {
                mDeviceInfo = (DeviceInfo) obj;
            }
        }

        @Override
        public void onReceive(Connection connection, List list) {
            if (list.isEmpty())
                return;

            if (list.get(0) instanceof AppInfo) {
                mAppAdapter.addAll(list);
                mAppAdapter.notifyDataSetChanged();
                List<String> needIconNames = new ArrayList<>();
                Set<String> existIconNames = mAppAdapter.getIcons().keySet();
                for (AppInfo appInfo : (List<AppInfo>) list) {
                    if (!existIconNames.contains(appInfo.packageName)) {
                        needIconNames.add(appInfo.packageName);
                    }
                }
                if (needIconNames.size() > 0) {
                    String arg = new Gson().toJson(needIconNames.toArray(new String[0]));
                    connection.sendMessage("app_icon", arg);
                }
            } else if (list.get(0) instanceof String) {
                mWatchFaceNames = list;
                mMyWatchFaceView.setText(null);
                for (String face : mWatchFaceNames) {
                    int dot = face.lastIndexOf(".");
                    mMyWatchFaceView.append(face.substring(dot + 1) + "\n");
                }
            }
        }
    };

    @Override
    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
        view.setBackgroundColor(Color.GRAY);
        getListView().addHeaderView(inflateHeader(), null, false);
        getListView().setDividerHeight(1);
        getListView().setBackgroundColor(Color.WHITE);
        if (mMyDevice != null) {
            mMyDeviceView.setText("我的设备 " + mMyDevice.getName());
        }
    }

    public static Map<String, Drawable> getAppIcons(Context context) {
        File imageDir = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/WatchManager/");
        File[] iconFiles = imageDir.listFiles();
        if(iconFiles==null){
            return new HashMap<>();
        }
        Map<String, Drawable> drawables = new HashMap<>(iconFiles.length);
        for (File file : iconFiles) {
            Drawable d = new BitmapDrawable(context.getResources(), file.getAbsolutePath());
            drawables.put(file.getName().replace(".png", ""), d);
        }
        return drawables;
    }

    private static String getAppIconPath(String name) {
        File imageDir = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/WatchManager/");
        if (!imageDir.exists()) {
            imageDir.mkdir();
        }
        String imagePath = imageDir.getAbsolutePath() + "/" + name + ".png";
        return imagePath;
    }

    public static void saveAppIconImage(String name, Bitmap bitmap) {
        try {
            File f = new File(getAppIconPath(name));
            if (f.exists()) {
                f.delete();
            }
            if (!f.createNewFile()) {
                return;
            }

            FileOutputStream fos = new FileOutputStream(f);
            if (null != fos) {
                bitmap.compress(Bitmap.CompressFormat.PNG, 90, fos);
                fos.flush();
                fos.close();
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}


